package es.juanc.mail.mio;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;

import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

import es.juanc.mail.mio.SmtpMail.AttachementFile;
import es.juanc.mail.mio.SmtpMail.MessageText;

public class SmtpSession {

	private static final int DEFAULT_PORT = 25;

	private String host;
	private int port;
	private String user;
	private String password;

	private boolean debug = false;
	private boolean tls = false;

	private class SmtpAuthenticator extends Authenticator {

		private String fUser;
		private String fPassword;

		public SmtpAuthenticator(String user, String password) {
			fUser = user;
			fPassword = password;
		}

		public PasswordAuthentication getPasswordAuthentication() {
			return new PasswordAuthentication(fUser, fPassword);
		}
	}
	
	public SmtpSession(String host) {
		this( host, DEFAULT_PORT, null, null );
	}

	public SmtpSession( String host, String user, String password ) {
		this( host, DEFAULT_PORT, user, password );
	}

	public SmtpSession( String host, int port, String user, String password ) {
		this.host = host;
		this.user = user;
		this.password = password;
		this.port = port;
	}

	public void setDebug( boolean value ) {
		debug = value;
	}

	public void setTls( boolean tls ) {
		this.tls = tls;
	}

	public void sendMail( SmtpMail mail ) throws MessagingException, IOException {
		
		// Creamos algunas de las propiedades y la sesion real en si misma
		Properties props = new Properties();
		
		// Nombre del host de correo, es smtp.gmail.com
		props.setProperty("mail.smtp.host", this.host);
		// Puerto de gmail para envio de correos
		props.setProperty("mail.smtp.port", String.valueOf(this.port));
		
		SmtpAuthenticator authenticator = null;
		if( this.user != null && this.password != null ) {
			// Si requiere o no usuario y password para conectarse.
			props.setProperty("mail.smtp.auth", "true");
			authenticator = new SmtpAuthenticator( this.user, this.password );
		}
		
		if( this.tls ) {
			// TLS si está disponible
			props.setProperty("mail.smtp.starttls.enable", "true");
		}
		
		Session session;
		if( authenticator == null ) {
			session = Session.getDefaultInstance( props );
		} else {
			session = Session.getDefaultInstance( props, authenticator );
		}
		
		session.setDebug( this.debug );

		// rellenamos ese mail real con los datos de nuestra clase auxiliar
		MimeMessage message = this.createMessage( session, mail );
		
		// finalmente enviamos el mail
		Transport.send( message );
	}

	private MimeMessage createMessage( Session session, SmtpMail mail ) throws MessagingException, 
			IOException {

		// creamos un mensaje de JavaMail real!
		MimeMessage message = new MimeMessage( session );

		// ajustamos las diferentes propiedades del mensaje
		message.setFrom( mail.getFrom() );
		message.setSubject( mail.getSubject() );
		message.setSentDate( new java.util.Date() );

		// ahora las distintas direcciones
		InternetAddress[] addresses = mail.getReplyToAddresses();
		if (addresses != null) {
			message.setReplyTo(addresses);
		}
		
		addresses = mail.getToAddresses();
		if (addresses != null) {
			message.setRecipients(Message.RecipientType.TO, addresses);
		}
		
		addresses = mail.getCcAddresses();
		if (addresses != null) {
			message.setRecipients(Message.RecipientType.CC, addresses);
		}
		
		addresses = mail.getBccAddresses();
		if (addresses != null) {
			message.setRecipients(Message.RecipientType.BCC, addresses);
		}
		
		// añadimos las partes del mensaje
		List bodyParts = new ArrayList( mail.getMessageTexts().size() + mail.getAttachements().size() );
		
		for( Iterator i = mail.getMessageTexts().iterator() ; i.hasNext() ; ) {
			MessageText mt  = (MessageText) i.next();
			MimeBodyPart mbp = new MimeBodyPart();
			mbp.setText( mt.getText() );
			if( mt.getCharset() == null && mt.getMimeType() == null ) {
				mbp.setText( mt.getText() );
			} else if( mt.getMimeType() == null ) {
				mbp.setText( mt.getText(), mt.getCharset() );
			} else {
				mbp.setText( mt.getText(), mt.getCharset(), mt.getMimeType() );				
			}
			bodyParts.add( mbp );
		}

		for( Iterator i = mail.getAttachements().iterator() ; i.hasNext() ; ) {
			AttachementFile attachement = (AttachementFile) i.next();
			MimeBodyPart mbp = new MimeBodyPart();
			mbp.attachFile( attachement.getFile() );
			mbp.setFileName( attachement.getNamet() );
			bodyParts.add( mbp );
		}

		// create the Multipart and its parts to it
		Multipart mp = new MimeMultipart();
		for( Iterator i = bodyParts.iterator() ; i.hasNext() ; ) {
			mp.addBodyPart( (MimeBodyPart) i.next() );
		}
		
		// add the Multipart to the message
		message.setContent( mp );

		return message;
	}
}